package controllers;

import java.util.*;
import java.text.SimpleDateFormat;

import play.*;
import play.mvc.*;
import play.data.*;

import models.*;
import views.html.staff.*;
import views.html.application.index;
import static play.data.Form.*;

import play.i18n.*;
import play.libs.Json;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;

public class Staff extends Controller {

	@With(LogSession.class)
	@Security.Authenticated(StaffSecured.class)
    public static Result refund(int view, String lang) {
		List<Payment> payment = Payment.findByStatus(lang, view);
		return ok(refunds.render(view, payment, Lang.forCode(lang)));
    }

	@With(LogSession.class)
	@Security.Authenticated(StaffSecured.class)
    public static Result authenticateRefund(long id , int toStatus, String lang) {
		Payment payment = Payment.findByID(id);

		if(payment == null)
			return internalServerError("System Error");

		payment.status = toStatus;
		payment.save();

		return redirect(routes.Staff.refund(1,lang));
    }

	@With(LogSession.class)
	@Security.Authenticated(ManagerSecured.class)
    public static Result movieManager(String lang) {
		List<Movie> movieList = Movie.findAll(lang);
		return ok(moviesSessionEditor.render(movieList, Lang.forCode(lang)));
    }

	@With(LogSession.class)
	@Security.Authenticated(ManagerSecured.class)
	public static Result sessionEditor(String lang) {
		List<Movie> movieList = Movie.findAll(lang);
		return ok(moviesSessionEditor.render(movieList, Lang.forCode(lang)));
    }

	@With(LogSession.class)
	@Security.Authenticated(ManagerSecured.class)
    public static Result houseManager(String lang) {
    	List<House> houseList = House.find.all();
		return ok(houses.render(houseList, Lang.forCode(lang)));
    }

	@With(LogSession.class)
	@Security.Authenticated(ManagerSecured.class)
    public static Result seatingPlan(Integer id, String lang) {
    	House house = House.find.byId(id);
		return ok(seatingPlan.render(house, form(HouseForm.class), Lang.forCode(lang)));
    }

    // POST
    public static Result editHouse() {
		Form<HouseForm> houseForm = form(HouseForm.class).bindFromRequest();
		int houseid = Integer.parseInt(houseForm.field("house").value());
		House bhouse = House.find.byId(houseid);


		if(houseForm.hasErrors()) {
			return badRequest(seatingPlan.render(bhouse, houseForm, Lang.forCode(houseForm.field("language").value())));
		} else {
			int id = houseForm.get().house;
			String language = houseForm.get().language;
			String[] seat = houseForm.get().seats.split(":");
			UnavailableSeat.resetSeats(id, seat);

			flash("house","staff.house.success");
    		return redirect(routes.Staff.houseManager(language));
    	}
    }

    // JSON REPSONSE
    @BodyParser.Of(BodyParser.Json.class)
    public static Result checkSeat(Integer id){
    	JsonNode json = request().body().asJson();
    	ObjectNode result = Json.newObject();

		List<UnavailableSeat> unavailable_records = UnavailableSeat.findByHouse(id);
    	String[] unavailable = new String[unavailable_records.size()];

    	for(int i=0;i<unavailable_records.size();i++){
	    	unavailable[i] = unavailable_records.get(i).seat_no;
    	}

    	result.put("unavailable", Json.toJson(unavailable));

    	return ok(result);
    }


	@With(LogSession.class)
	@Security.Authenticated(ManagerSecured.class)
    public static Result statistics(String lang) {
		//Logger.info(String.valueOf(Payment.findSalesByHouseId(1)));
		//Logger.info(String.valueOf(Payment.findSalesByYearAndMonth(2013,5)));
		return ok(statistics.render(Lang.forCode(lang)));
    }

	@BodyParser.Of(BodyParser.Json.class)
    public static Result getStats(){
    	JsonNode json = request().body().asJson();
    	ObjectNode result = Json.newObject();



    	int[] monthlyStats = new int[5];
		int[] houseStats = new int[4];

    	for(int i=3;i<8;i++){
	    	monthlyStats[i-3] = Payment.findSalesByYearAndMonth(2013,i);
    	}

		for(int i=1; i<5; i++){
			houseStats[i-1] = Payment.findSalesByHouseId(i);
		}

    	result.put("monthlyStats", Json.toJson(monthlyStats));
		result.put("houseStats" , Json.toJson(houseStats));

    	return ok(result);
    }

    @With(LogSession.class)
	@Security.Authenticated(StaffSecured.class)
	public static Result sale(String lang) {
		List<Movie> movies = Movie.sale(lang);
		return ok(sale.render(movies, form(SaleForm.class), Lang.forCode(lang)));
	}

	@With(LogSession.class)
	@Security.Authenticated(StaffSecured.class)
	public static Result ticketing(String session, String lang) {
		Form<SaleForm> saleForm = form(SaleForm.class).bindFromRequest();

		if(saleForm.hasErrors()) {
			List<Movie> movies = Movie.sale(lang);
			return badRequest(sale.render(movies, saleForm, Lang.forCode(lang)));
		} else {
			String[] sessions = saleForm.get().session.split(",");
			List<MovieSession> movieSessions = new java.util.ArrayList<MovieSession>();
			for(int i=0;i<sessions.length;i++){
				MovieSession movieSession = MovieSession.findById(Long.parseLong(sessions[i]), lang);
				movieSessions.add(movieSession);
			}

			return ok(ticket.render(movieSessions, form(TicketForm.class), Lang.forCode(lang)));
		}
	}

	public static Result payment() {
		Form<TicketForm> ticketForm = form(TicketForm.class).bindFromRequest();

		String lang = ticketForm.field("lang").value();
		if(lang == null)
			lang = "en";

		String session = ticketForm.field("session").value();
		String[] sessions = (session.substring(1)).split(":");

		if(ticketForm.hasErrors()) {

			List<MovieSession> movieSessions = new java.util.ArrayList<MovieSession>();
			for(int i=0;i<sessions.length;i++){
				MovieSession movieSession = MovieSession.findById(Long.parseLong(sessions[i]), lang);
				movieSessions.add(movieSession);
			}

			return badRequest(ticket.render(movieSessions, ticketForm, Lang.forCode(lang)));
		} else {
			String[] seat = ticketForm.get().seat.split(",");

			// 3:A3,3:A4,4:C1..
			// sessions[0] = 3, sessions[1] = 4
			// String[0][0] = A3, String[0][1] = A4, String[1][0] = C1

			HashMap<String, List<String>> temp =  new HashMap<String, List<String>>();

			for(int i=0; i<seat.length; i++) {
				String[] tSeat = seat[i].split(":");
				List<String> seats = temp.get(tSeat[0]);
				if(seats == null) {
					seats = new ArrayList<String>();
				}
				seats.add(tSeat[1]);
				temp.put(tSeat[0], seats);
			}

			String uuid = session("uuid");
			String username = LogSession.getUsernameFromUUID(uuid);
			String email = User.findByUser(username).email;
			String credit_card = User.findByUser(username).credit_card;

			for(int i=0;i<sessions.length;i++){
				List<String> seats = temp.get(sessions[i]);
				if(seats != null) {
					for(int j=0;j<seats.size();j++){
							new Payment(Long.parseLong(sessions[i]), seats.get(j), email, credit_card, username, 0).save();
					}
				}
			}

			flash("payment","movie.payment.success");
			return redirect(routes.Application.index(lang));
		}
	}

	@With(LogSession.class)
	@Security.Authenticated(StaffSecured.class)
	public static Result editSession(Long id, String lang){
		Form<MovieSessionEditForm> movieSessionEditForm = form(MovieSessionEditForm.class);

		MovieSessionEditForm sessionData = new MovieSessionEditForm();
    	MovieSession session = MovieSession.findById(id, lang);

		sessionData.id = session.id;
		sessionData.price = session.price;
		sessionData.house_id = session.house.id;
		sessionData.movieLang = session.lang;

		movieSessionEditForm = movieSessionEditForm.fill(sessionData);

	    return ok(moviesSessionEditorEditing.render(session, movieSessionEditForm, Lang.forCode(lang)));
    }

	@With(LogSession.class)
	@Security.Authenticated(StaffSecured.class)
	public static Result removeSession(Long id, String lang){

    	MovieSession session = MovieSession.findById(id, lang);

		if(Payment.isMovieSessionPurchasedByAnyone(id)){
			flash("error","There exists payment(s) for this Movie Session. No modification could be done without refunding all the existing payment(s) for this Movie Session.");
			return redirect(routes.Staff.sessionEditor(lang));
		}

		if(session == null){
			flash("error","Invalid session");
			return redirect(routes.Staff.sessionEditor(lang));
		}

		session.delete();

	    return redirect(routes.Staff.sessionEditor(lang));
    }

	@With(LogSession.class)
	@Security.Authenticated(StaffSecured.class)
	public static Result createSession(Long movieId, String lang){
		Movie movie = Movie.findById(movieId,lang);

		if(movie == null)
			return notFound();

	    return ok(moviesSessionEditorCreating.render(movie, null, form(MovieSessionCreateForm.class), Lang.forCode(lang)));
    }

	// POST
	public static Result submitSessionCreation(){
		Form<MovieSessionCreateForm> movieSessionCreateForm = form(MovieSessionCreateForm.class).bindFromRequest();


		String lang = movieSessionCreateForm.field("lang").value();
		if(lang == null)
			lang = "en";

		Long movie_id = Long.parseLong(movieSessionCreateForm.field("movie_id").value());
		if (movie_id == null)
			return notFound();

		String l_showtime = movieSessionCreateForm.field("showtime").value();
		Date showtime = null;
		if(l_showtime != null){
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");

			try{
				showtime = sdf.parse(l_showtime);
			}catch(Exception e)
			{
				Movie movie = Movie.findById(movie_id,lang);
				return badRequest(moviesSessionEditorCreating.render(movie, null, movieSessionCreateForm, Lang.forCode(lang)));
			}
		}

		if(movieSessionCreateForm.hasErrors()) {
			Movie movie = Movie.findById(movie_id,lang);
			return badRequest(moviesSessionEditorCreating.render(movie, showtime, movieSessionCreateForm, Lang.forCode(lang)));
		} else {
			MovieSessionCreateForm data = movieSessionCreateForm.get();

			MovieSession session = new MovieSession();
			session.price = data.price;
			session.movie = Movie.findById(data.movie_id, data.lang);
			session.house = House.findById(data.house_id);
			session.lang = data.movieLang;
			session.showtime = showtime;
			session.save();

			return redirect(routes.Staff.sessionEditor(lang));
		}
	}

	// POST
	@With(LogSession.class)
	public static Result submitSessionEdit(){
		Form<MovieSessionEditForm> movieSessionEditForm = form(MovieSessionEditForm.class).bindFromRequest();


		String lang = movieSessionEditForm.field("lang").value();
		if(lang == null)
			lang = "en";

		Long id = Long.parseLong(movieSessionEditForm.field("id").value());
		if (id == null)
			return internalServerError("System Error");

		if(movieSessionEditForm.hasErrors()) {
			MovieSession session = MovieSession.findById(id, lang);
			return badRequest(moviesSessionEditorEditing.render(session, movieSessionEditForm, Lang.forCode(lang)));
		} else {
			MovieSessionEditForm data = movieSessionEditForm.get();


			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");
			Date showtime;

			try{
				showtime = sdf.parse(data.showtime);
			}catch(Exception e)
			{
				return internalServerError("System Error");
			}

			//Logger.info(data.showtime);
			//Logger.info(showtime.toString());
			MovieSession session = MovieSession.findById(data.id, lang);
			session.price = data.price;
			session.house = House.findById(data.house_id);
			session.lang = data.movieLang;
			session.showtime = showtime;
			session.save();

			return redirect(routes.Staff.sessionEditor(lang));
		}
	}


}